# gozerlib/utils/generic.py
#
#

""" generic functions. """

## gozerlib imports 

from exception import handle_exception
from trace import calledfrom
from lazydict import LazyDict

## simplejson import

from waveapi.simplejson import dumps

## generic imports

import time
import sys
import re
import getopt
import types
import os
import random
import Queue 
import logging

def getwho(bot, nick):

    """ return userhost for nick. NOT IMPLEMENTED YET .. return the nick. """

    return nick

def jsonstring(input):

    """ convert input to a json string. """

    if type(input) == types.TupleType:
        input = list(input)
    return dumps(input)

def getversion(txt=""):

    """ return a version string. """

    from gozerlib.config import cfg
    return cfg.get('version') + ' ' + txt

def makeoptions(ievent, options={}):

    """ create options from event.txt. """

    options = LazyDict(options)
    try:
        optargs = ""
        optlist = []
        if not options.has_key('--filter'):
            options['--filter'] = ""
        if not options.has_key('--to'):
            options['--to'] = None
        if not options.has_key('--chan'):
            options['--chan'] = ievent.channel
        if not options.has_key('--how'):
            options['--how'] = "msg"
        if not options.has_key('--speed'):
            options['--speed'] = str(ievent.speed)
        else:
            options['--speed'] = str(options['--speed'])
        for i, j in options.iteritems():
            if '--' in i:
                optlist.append("%s=" % i[2:])
                if j:
                    optlist.append(j)
                continue
            if '-' in i:
                if j:
                    optargs += ":%s" % i[1:]
                else:
                    optargs += i[1:]
        args = ievent.txt.split()
        try:
            (opts, rest) = getopt.getopt(args[1:], optargs, optlist)
        except AttributeError, ex:
            print "option not allowed: %s" % str(ex), ievent.txt, options
            return 0
        except getopt.GetoptError, ex:
            return 0
        if opts:
             for item in opts:
                 ievent.optionset.append(item[0])
        o = dict(options)
        o.update(dict(opts))
        try:
            filter = o['--filter']
            if filter and filter not in ievent.filter:
                ievent.filter.append(filter)
        except KeyError:
            pass
        try:
            speed = o['--speed']
            ievent.speed = int(speed)
        except KeyError:
            pass
        try:
            ievent.channel = o['--chan'] or ievent.channel
        except KeyError:
            pass
        ievent.options.update(o)
        if args:
            ievent.txt = args[0] + ' ' + ' '.join(rest)
        makeargrest(ievent)
    except Exception, ex:
        handle_exception()
        return 
    return ievent.options

def plugfile(datadir):

    """ return plugin file. """

    return datadir + os.sep + calledfrom(sys._getframe())

def splittxt(what, l=375):

    """ split output into seperate chunks. """

    txtlist = []
    start = 0
    end = l
    length = len(what)

    for i in range(length/end+1):
        endword = what.find(' ', end)

        if endword == -1:
            endword = length

        res = what[start:endword]

        if res:
            txtlist.append(res)

        start = endword
        end = start + l

    return txtlist
    
class istr(str): 

    """ convenience class to store attributes on a string. """

    pass

def getrandomnick():

    """ return a random nick. """

    return "gwbot" + str(random.randint(0, 100))

def decodeperchar(txt, encoding='utf-8', what=""):

    """ decode a string char by char. strip chars that can't be decoded. """

    res = []
    nogo = []

    for i in txt:
        try:
            res.append(i.decode(encoding))
        except UnicodeDecodeError:
            if i not in nogo:
                nogo.append(i)
            continue

    if nogo:
        if what:
            logging.debug("%s: can't decode %s characters to %s" % (what, nogo, encoding))
        else:
            logging.debug("can't decode %s characters to %s" % (nogo, encoding))

    return u"".join(res)

def toenc(what, encoding='utf-8'):

    """ convert to encoding. """

    if not what:
        what=  u""

    try:
        w = unicode(what)
        return w.encode(encoding)
    except UnicodeEncodeError:
        logging.debug("can't encode %s to %s" % (what, encoding))
        return u""

def fromenc(txt, encoding='utf-8', what=""):

    """ convert from encoding. """

    if not txt:
        txt = u""
    try:
        if type(txt) == types.UnicodeType:
            t = txt.encode(encoding)
        t = unicode(txt)
        return unicode(t.decode(encoding))
    except UnicodeDecodeError:
        return decodeperchar(txt, encoding, what)

def toascii(what):

    """ convert to ascii. """

    what = what.encode('ascii', 'replace')
    return what

def tolatin1(what):

    """ convert to latin1. """

    what = what.encode('latin-1', 'replace')
    return what

def strippedtxt(what, allowed=[]):

    """ strip control characters from txt. """

    txt = []
    allowed = allowed + ['\001', '\002', '\003', '\t']
    for i in what:
        if ord(i) > 31 or (allowed and i in allowed):
            txt.append(i)
    return ''.join(txt)

def uniqlist(l):

    """ return unique elements in a list (as list). """

    result = []

    for i in l:
        j = i.strip()
        if j not in result:
            result.append(j)

    return result

def jabberstrip(text, allowed=[]):

    """ strip control characters for jabber transmission. """

    txt = []
    allowed = allowed + ['\n', '\t']

    for i in text:
        if ord(i) > 31 or (allowed and i in allowed):
            txt.append(i)

    return ''.join(txt)

def plugnames(dirname):

    """ return all plugin names of plugins in a directory. """

    result = []

    for i in os.listdir(dirname):
        if os.path.isdir(dirname + os.sep + i):
            if os.path.exists(dirname + os.sep + i + os.sep + '__init__.py'):
                result.append(i)
        elif i.endswith('.py'):
            result.append(i[:-3])

    try:
        result.remove('__init__')
    except:
        pass

    return result

def filesize(path):

    """ return filesize of a file. """

    return os.stat(path)[6]

def touch(fname):

    """ touch a file. """

    fd = os.open(fname, os.O_WRONLY | os.O_CREAT)
    os.close(fd)  

def stringinlist(s, l):

    """ check is string is in list of strings. """

    for i in l:     
        if s in i:  
            return 1

def stripped(userhost):

    """ return a stripped userhost (everything before the '/'). """ 

    return userhost.split('/')[0]

def gethighest(ddir, ffile):

    """ get filename with the highest extension (number). """

    highest = 0

    for i in os.listdir(ddir):

        if os.path.isdir(ddir + os.sep + i) and ffile in i:
            try:
                seqnr = i.split('.')[2]
            except IndexError:
                continue

            try:
                if int(seqnr) > highest:
                    highest = int(seqnr)
            except ValueError:
                pass

    ffile += '.' + str(highest + 1)
    return ffile

def waitforqueue(queue, timeout=10, maxitems=None):

    """ wait for results to arrive in a queue. return list of results. """

    result = []

    while 1:
        try:   
            res = queue.get(1, timeout)
        except Queue.Empty:
            continue

        if not res:
            break 

        result.append(res)

        if maxitems and len(result) == maxitems:
            break

    return result

